module.exports = function () {
    var express = require('express');
    var socketiojwt = require('socketio-jwt');
    var _ = require('underscore');

    var User = require('./models/user');
    var Question = require('./models/question');
    var options = require('./options');

    var server = require('./app');
    var io = require('socket.io')(server);

// client side connect
// var socket = io.connect(url, {'query':'token='+jwt});

// client handle error
// {code: , event: , msg: }
// socket.on('error', function(error){ dealing with the error});

    var sockets = [];
    var groups = [];

    function genErr(event, req, message) {
        return {event: event, req: req, message: message};
    }

    io.use(socketiojwt.authorize({
        secret: options.jwtSecret,
        handshake: true
    }));

    io.on('connection', function (socket) {
        var _id = socket.decoded_token.id;
        var _username = socket.decoded_token.username;

        sockets[_username] = socket;

        socket.on('create', function (data) {
            data = data || {};
            var gid = data.gid;
            Question.findById(gid, function (err, question) {
                if (err || !question) {
                    socket.emit('err', genErr('create', data, 'invalid gid'));
                    return;
                }
                if (groups[gid]) {
                    socket.emit('err', genErr('create', data, 'group already exists'));
                } else {
                    groups[gid] = [];
                    socket.emit('created', {gid: gid});
                }
            });
        });

        // {gid: question id as room id}
        socket.on('join', function (data) {
            data = data || {};
            var gid = data.gid;
            if (!groups[gid]) {
                socket.emit('err', genErr('join', data, 'group not found'));
                return;
            }
            if (!_.contains(groups[gid], _username)) {
                socket.join(gid);
                groups[gid].push(_username);
            }
            socket.emit('joined', {gid: gid, member: groups[gid]});
            socket.to(gid).emit('user joined', {gid: gid, username: _username});
            console.log(socket.rooms);
        });

        // {gid:question id as room id}
        socket.on('leave', function (data) {
            data = data || {};
            var gid = data.gid;
            if (!groups[gid]) {
                socket.emit('err', genErr('leave', data, 'group not found'));
                return;
            }
            if (_.contains(groups[gid], _username)) {
                socket.leave(gid);
                groups[gid].splice(_.indexOf(groups[gid], _username), 1);
                socket.emit('left', {gid: gid});
                if (_.isEmpty(groups[gid])) {
                    delete groups[gid];
                } else {
                    socket.to(gid).emit('user left', {gid: gid, username: _username});
                }
            } else {
                socket.emit('err', genErr('leave', data, 'not group member'));
            }
            console.log(socket.rooms);
        });

        //{id: question id as msg id, msg: }
        socket.on('gmsg', function (data) {
            data = data || {};
            var gid = data.gid;
            if (!groups[gid]) {
                socket.emit('err', genErr('gmsg', data, 'group not found'));
                return;
            }
            if (_.contains(groups[gid], _username)) {
                socket.to(gid).emit('gmsg', {gid: gid, username: _username, msg: data.msg});
            } else {
                socket.emit('err', genErr('gmsg', data, 'not group member'));
            }
        });

        socket.on('disconnect', function () {
            console.log('dis');
            var rooms = socket.rooms;
            console.log(socket.rooms);
            console.log(rooms);
            var len = rooms.length;
            console.log(len);
            for (var i = 0; i < len; ++i) {
                if (rooms[i] !== socket.id) {
                    var gid = rooms[i];
                    console.log(gid);
                    if (groups[gid] && _.contains(groups[gid], _username)) {
                        groups[gid].splice(_.indexOf(groups[gid], _username), 1);
                        if (_.isEmpty(groups[gid])) {
                            delete groups[gid];
                        } else {
                            socket.to(gid).emit('user left', {gid: gid, username: _username});
                        }
                    }
                }
            }
    	delete sockets[_username];
        });
		
		socket.on('sendByU', function (msg) {
            msg = msg || {};
            if (msg.name && msg.msg) {
				if(sockets[msg.name]){
					sockets[msg.name].emit('reveiveByU', {msg: msg.msg, name: _username});
				}else {
					socket.emit('error', {event: 'sendByU', msg: msg, code: 'user not found'});
				}
            } else {
                socket.emit('error', {event: 'sendByU', msg: msg, code: 'invalid info'});
            }
        });
		
		socket.on('sendByQU', function (msg) {
            msg = msg || {};
			if (msg.name && msg.msg && msg.question) {
				Question.findById(msg.qid, function (err, question) {
					if (err) {
                        socket.emit('error', {event: 'sendByQU', msg: msg, code: 'internal error'});
                    } else {
                        if (!question) {
                            socket.emit('error', {event: 'sendByQU', msg: msg, code: 'question not found'});
                        } else {
							if(sockets[msg.name]){
								sockets[msg.name].emit('receiveByQid',{question: msg.question, msg: msg.msg});
							}else {
								socket.emit('error', {event: 'sendByQU', msg: msg, code: 'user not found'});
							}
                        }
                    }
					
				});
            } else {
                socket.emit('error', {event: 'sendByQU', msg: msg, code: 'invalid info'});
            }
        });
		
		socket.on('sendByQid', function (msg) {
            msg = msg || {};
            if (msg.question && msg.msg) {
				Question.findById(msg.question, function (err, question) {
                    if (err) {
                        socket.emit('error', {event: 'sendByQid', msg: msg, code: 'internal error'});
                    } else {
                        if (!question) {
                            socket.emit('error', {event: 'sendByQid', msg: msg, code: 'question not found'});
                        } else {
							Question.findById(question.creator, function (err, user) {
								if (err) {
									socket.emit('error', {event: 'sendByQid', msg: msg, code: 'internal error'});
								} else {
									if (!user) {
										socket.emit('error', {event: 'sendByQid', msg: msg, code: 'user not found'});
									} else {
										sockets[user.name].emit('receiveByU',{name: _username, msg: msg.msg});
										//socket.to(msg.id).emit('user join', {room: msg.id, user: username});
									}
								}
							});
							//socket.to(msg.id).emit('user join', {room: msg.id, user: username});
                        }
                    }
                });
            } else {
                socket.emit('error', {event: 'sendByQid', msg: msg, code: 'invalid info'});
            }
        });
		
		
            
    });
};